<?php

/**
 * Source code for Global Trade Item Number [GTIN]. 
 *
 * Source code for Global Trade Item Number [GTIN] at boapi.
 *
 * PHP version 5.3
 *
 * LICENSE: Licensed this file to you under the Apache License, 
 * Version 2.0 (the "License"); you may not use this file except 
 * in compliance with the License. You may obtain a copy of the 
 * License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 * @category   CategoryName
 * @package    boapi
 * @author     Sebastian Ritter <sebastian.2009@ritter.biz>
 * @copyright  2009 Sebastian Ritter
 * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
 * @version    2.0.0.0
 * @see        http://www.boapi.org
 * @link       http://pear.php.net/package/PackageName
 * @since      File available since Release 0.2.0
 */

/** define namespace */
namespace org\boapi\shop;
/** import base interface IChecknumber file */
include_once (__DIR__ . '/IChecknumber.php');


/**
 * Global Trade Item Number [GTIN] is a 13 digits number or as ISBN 13 with an X as check digit.
 *
 * Global Trade Item Number [GTIN] is a 13 digits number or as ISBN 13 
 * with an X as check digit. Since 2005 GTIN International and American 
 * UCC merge to GS1 and also EAN and UPC now named as GTIN.
 *
 * @category   CategoryName
 * @package    boapi
 * @author     Sebastian Ritter <sebastian.2009@ritter.biz>
 * @copyright  2009 Sebastian Ritter
 * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
 * @version    3.0.0.0 Release: @package_version@
 * @link       http://www.gs1-germany.de/
 * @see        org::boapi::core::IChecknumber
 */
class GTIN implements \org\boapi\core\IChecknumber {

  /**
   * Create an GTIN from ISBN-13
   * @param isbn
   * @return GTIN
   */
  public static function parse ($isbn13) {
    $gtin = new GTIN ();
    $gtin->setCompleteValue ($isbn13);
    return $gtin;
  }
  /**
   * Global Trade Item Number 
   */
  private $number='';

  /**
   * Set the Global Trade Item Number [GTIN]
   * @param gtin
   */
  public function setCompleteValue ($gtin) {
    $num = '';
    if (is_array ($gtin)) {
      $gtin = $gtin [0];
    }
    $gtin =strtoupper($gtin);
    for ($i = 0; $i < strlen($gtin); $i++) {
      if (is_numeric(substr($gtin,$i,1)) || 'X' == substr($gtin,$i,1)) {
        $num = $num . substr($gtin,$i,1);
      }
      elseif ( '.' != substr($gtin,$i,1) ) {
	    throw new exception ("Illegal character in GTIN $gtin");
      }
    }
    while (strlen ($num) < 13) {
      $num = '0'.$num;
    }
    $this->number = $num;
    $this->setChecknumber ('R');
  }

  /**
   * The number of GTIN
   * @return GTIN number
   */
  public function getNumber () {
    return $this->number;
  }
  /** The check digit
   */
  private $checknumber = 'R';
  /** Set the check digit
   * @param checkdigit
   */
  function setChecknumber ($checkdigit) {
    $this->checknumber = $checkdigit;
  }
  /** Get the check digit
   * @return checknumber check digit
   */
  function getChecknumber () {
    if ('R' == $this.$checknumber) {
      $this->isChecknumberCorrect ();
    }
    return $this.$checknumber;
  }
  /** Is the checknumber correct
   * @return boolean is correct
   */
  public function isChecknumberCorrect () {
    $factors = array(1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3);
    $digits = array();
    
    for ($i = 0; $i < count ($factors); $i++) {
  	  $digits[$i] = substr ($this->getNumber(),$i,1);
    }
    $sum = 0;
    for ($i = 0; $i < count($digits); $i++) {
      $sum += $digits[$i] * $factors[$i];
    }
    $checknumber = 10-($sum % 10);
    $this->setChecknumber (substr($checknumber,0,1));
    return $this->getChecknumber() == substr($this->getNumber(),12,1);
  }


  /**
   * If GTIN starts with 45 or 47 it is also called Japanese Article Number
   * @return boolean GTIN is Japanese Article Number
   */
  public function isJAN () {
    $ok = false;
    if ('45' == substr ($this->getNumber (),0, 2) ||
        '49' == substr ($this->getNumber (),0, 2)) {
      $ok = true;
    }
    return $ok;
  }
  /** i18n detail information
   */
  private static $localization = array ();

  /**
   * Load the i18n detail informations for setting locale language
   * @see Locale.setDefault()
   */
  private static function loadGTINLocale () {
  	$lang ='en'; // default
   	if ('cgi'==php_sapi_name()) { // CLI
   	  $lang = \Locale::getPrimaryLanguage(Locale::getDefault ());
   	}
   	else { // HTTP - with @ because, PHP notice on CLI 
   	  @$lang = \Locale::getPrimaryLanguage(\Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']));
   	}
	$langFound = 'NOT_READED';

	$locale = null;
  	$xml_file = new \XMLReader();
  	$xml_file->open(__DIR__ . '/GTIN.xml');
  	$gtinRes = simplexml_load_file (__DIR__ . '/GTIN.xml');
	while($xml_file->read() && 'READED' != $langFound) {
	 switch($xml_file->nodeType) {
	  case \XMLReader::ELEMENT:
	    if ('gtin' == $xml_file->localName){ 
	      if ($lang == $xml_file->getAttribute('lang')) {
	        $langFound = 'READING';
	      }
	    } elseif ('detail' == $xml_file->localName) {
	      $locale = $xml_file->getAttribute('locale');
	    }
	    break;
	
	  case \XMLReader::TEXT:
	    GTIN::$localization [$xml_file->value] = $locale;
	    break;
	
	  case \XMLReader::END_ELEMENT:
	    if ($langFound && 'gtin' == $xml_file->localName) {
	      $langFound = 'READED';
	    }
	    break;
	 }
	}
	$xml_file->close();
  }

  /**
   * Return an internationalized GTIN localization or empty string if unknown
   * @return location
   */
  public function getLocation () {
  	if (0 == sizeof(GTIN::$localization)) {
  	  GTIN::loadGTINLocale();
  	}
  	$local = ''; //@TODO: Defaultwert auswerten 
    $startsWith = substr ($this->getNumber(),0, 4); // change for ISMN
    if (array_key_exists ($startsWith, GTIN::$localization)) {
      $local = GTIN::$localization [$startsWith];
    }
    else {
      $startsWith = substr ($this->getNumber(),0, 3);
	  if (array_key_exists ($startsWith, GTIN::$localization)) {
	    $local = GTIN::$localization [$startsWith];
	  }
	  else {
	  	$startsWith = substr ($this->getNumber(),0, 2);
	    if (array_key_exists ($startsWith, GTIN::$localization)) {
	      $local = GTIN::$localization [$startsWith];
	    }
	    else {
		  $startsWith = substr ($this->getNumber(),0, 1);
	      if (array_key_exists ($startsWith, GTIN::$localization)) {
	        $local = GTIN::$localization [$startsWith];
		  }
		  else {} // local has the default value
	    }
	  }
	}
    return $local;
  }
}
?>
